/**
 * @author:albert
 */

package com.bkbw.live.battle.business;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Vector;

import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;

import com.badlogic.gdx.scenes.scene2d.ui.Value;
import com.bkbw.live.common.notifycenter.GameNotifyHandler;
import com.bkbw.live.common.dataproto.EnumConfigPb.*;
import com.bkbw.live.battle.business.skill.AbilityBase;
import com.bkbw.live.battle.business.skill.AbilityFactory;
import com.bkbw.live.battle.business.skill.BuffBase;
import com.bkbw.live.battle.business.skill.BuffFactory;

public class GameObject implements GameNotifyHandler{
	
	protected int id;
	public int getId() {
		return id;
	}
	
	public enum GameObjectGroup {
		Neutral(0), UserGroup1(1), UserGroup2(2), Monster(3);
		private GameObjectGroup(int i) {
			value = i;
		}
		private int value;
		public int value() {
			return value;
		}
	}
	
	protected GameObjectGroup group;

	public GameObjectGroup getGroup() {
		return group;
	}

	public void setGroup(GameObjectGroup group) {
		this.group = group;
	}

	protected GameLogicMap map;
	
	public GameLogicMap getMap()
	{
		return this.map;
	}
	
	protected float speedLen;
	
	public float getSpeedLen() {
		return speedLen;
	}
	
	public void setSpeedLen(float speedLen) {
		this.speedLen = speedLen;
	}

	protected Vector3D speed;
	protected Vector3D head;
	
	public Vector3D getSpeed() {
		return this.speed;
	}
	
	public void setSpeed(Vector3D speed) {
		this.speed = new Vector3D(speed.getX(), speed.getY(), speed.getZ());
		speedLen = (float)speed.getNorm();
	}
	
	public Vector3D getHead() {
		return this.head;
	}
	
	public void setHead(Vector3D head) {
		this.head = new Vector3D(speed.getX(), speed.getY(), speed.getZ());
	}
	
	public void setSpeedAndHead(Vector3D speed)  {
		setSpeed(speed);
		setHead(speed);
		
	}
	
	protected boolean isMoving = false;
	
	public void setMoving(boolean move) 
	{
		isMoving = move;
	}
	
	public boolean isMoving() 
	{
		return isMoving;
	}
	
	protected Vector3D position;// = new Vector3D(1, 0, 1);
	
	public Vector3D getPosition() {
		return position;
	}

	public void setPosition(Vector3D position) {
		//System.out.println("id " + id + " pos "+position);
		this.position = position;
	}

	
	

	protected HashMap<String, BehaviorBase> behaviors = new HashMap<String, BehaviorBase>();
	protected HashMap<String, LinkedList<BuffBase>> buffs = new HashMap<String, LinkedList<BuffBase>>();
	
	public GameObject(int id, GameLogicMap map)
	{
		this.id = id;
		this.map = map;
	}
	
	
	
	public void update(float dt)
	{
		try {
			for (String key : this.behaviors.keySet()) {
				BehaviorBase behavior = this.behaviors.get(key);
				if (behavior == null) {
					System.out.println("imporssible");
				}
				behavior.update(dt);
			}
			for (String key : this.buffs.keySet()) {
				LinkedList<BuffBase> list = this.buffs.get(key);
				for (BuffBase buff : list) {
					buff.update(dt);
				}
			}
		}
		catch (Exception e){
			System.out.println("class is " + this.getClass().getName());
			System.out.println("id is " + this.getId());
			e.printStackTrace();
		}
	}
	
	public boolean attackable()
	{
		return false;
	}
	
	public boolean eatable()
	{
		return false;
	}
	
	public boolean collision()
	{
		return false;
	}
	

	
	// ----------------- buff, behavior ----------
	public void unbindAll()
	{
		
		
		for (String key : this.behaviors.keySet()) {
			unbindBehavior(key);
		}
		
		for (String key: this.buffs.keySet()) {
			LinkedList<BuffBase> list = this.buffs.get(key);
			for (BuffBase buffBase : list) {
				unbindBuff(buffBase);
			}
		}
	}
	
	public boolean hasBuff(String buffId)
	{
		return this.buffs.containsKey(buffId) && (this.buffs.get(buffId).size() > 0);
	}
	
	public void bindBuff(String buffClass, String buffId, HashMap<String, Object> param)
	{
		if (!hasBuff(buffId)) {
			BuffFactory factory = BuffFactory.getInstance();
			BuffBase buff = (BuffBase)factory.createBuff(buffClass, buffId, param);
			buff.bind(this);
			LinkedList<BuffBase> list = new LinkedList<BuffBase>();
			list.add(buff);
			this.buffs.put(buffId, list);
			this.buffs.get(buff);
		}
		else {
			BuffBase buff = this.buffs.get(buffId).get(0);
			BuffAccumulate accumulate = buff.getAccumulate();
			switch (accumulate.getNumber()) {
			case BuffAccumulate.AccumulateDefault_VALUE:
				{
					BuffFactory factory = BuffFactory.getInstance();
					BuffBase newbuff = (BuffBase)factory.createBuff(buffClass, buffId, param);
					newbuff.bind(this);
					this.buffs.get(buffId).add(newbuff);
					break;
				}
			case BuffAccumulate.AccumulateReset_VALUE:
				{
					buff.AccumulateReset(param);
					break;
				}
			case BuffAccumulate.AccumulateTime_VALUE:
				{
					buff.AccumulateTime(param);
				}
			case BuffAccumulate.AccumulateEffect_VALUE:
				{
					buff.AccumulateEffect(param);
				}
			}
		}
	}
	
	public void unbindBuff(BuffBase buff)
	{
		LinkedList<BuffBase> list = this.buffs.get(buff.getBuffId());
		buff.unbind();
		list.remove(buff);
	}
	
	public boolean hasBehavior(String behaviorClass)
	{
		return this.behaviors.containsKey(behaviorClass);
	}
	
	public void bindBehavior(String behaviorClass, HashMap<String, Object> param)
	{
		if (hasBehavior(behaviorClass)) {
			return;
		}
		BehaviorFactory factory = BehaviorFactory.getInstance();
		BehaviorBase behavior = (BehaviorBase)factory.createBehavior(behaviorClass, param);
		behavior.bind(this);
		this.behaviors.put(behaviorClass, behavior);
	}
	
	public BehaviorBase getBehavior(String behaviorClass) {
		if (hasBehavior(behaviorClass)) {
			return this.behaviors.get(behaviorClass);
		}
		return null;
	}
	
	public void unbindBehavior(String behaviorClass) 
	{
		if (hasBehavior(behaviorClass)) {
			BehaviorBase behavior = this.behaviors.get(behaviorClass);
			behavior.unbind();
			this.behaviors.remove(behaviorClass);
		}
	}
	
	@Override
	public void handle(Object sender, Object param)
	{
		
	}

	// ----------- getter & setter --------
	
}







